package com.linran.gclearn.jvm.sync;

import com.linran.gclearn.jvm.dispatch.Overload;

import java.util.Vector;

/**
 * 绝对线程安全测试
 */
public class VectorTest {
    private static Vector<Integer> vector = new Vector<>();


    public static void main(String[] args) {
        syncSecurity();
    }

    /**
     * 	虽然vector的add、remove、get方法都有synchronized保证各自对应方法的同步操作，但是却无法保障vector内的数据访问与删除或者添加同步
     * 	所以即使是线程安全的类每次添加，删除，访问都需要进行操作之间进行排队有序访问vector
     *
     * 	思考：这里add为什么不用synchronized
     */
    public static void syncSecurity() {
        while (true) {
            for (int i = 0; i < 10; i++) {
                vector.add(i);
            }

            Thread removeThread = new Thread(() -> {
                // 这里编译器提示vector需要进行final修饰，但是不妨碍本次结果
                synchronized (vector) { //对vector同步
                    for (int i = 0; i < vector.size(); i++) {
                        vector.remove(i);
                    }
                }
            });

            Thread printThread = new Thread(() -> {
                synchronized (vector) { //对vector同步
                    for (int i = 0; i < vector.size(); i++) {
                        System.out.println(vector.get(i));
                    }
                }
            });

            removeThread.start();
            printThread.start();
            //不要同时产生过程的线程，否则会导致操作系统假死
            while (Thread.activeCount() > 20);
        }
    }

    /**
     * Exception in thread "Thread-70687" java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 12
     * 	at java.util.Vector.get(Vector.java:748)
     * 	at com.linran.gclearn.jvm.sync.VectorTest.lambda$main$1(VectorTest.java:25)
     * 	at java.lang.Thread.run(Thread.java:748)
     *
     * 	虽然vector的add、remove、get方法都有synchronized保证各自对应方法的同步操作，但是还是会有问题，比如当get需要访问的数据被remove掉
     * 	后，就会报ArrayIndexOutOfBoundsException
     */
    public static void syncProblem() {
        while (true) {
            for (int i = 0; i < 10; i++) {
                vector.add(i);
            }

            Thread removeThread = new Thread(() -> {
                for (int i = 0; i < vector.size(); i++) {
                    vector.remove(i);
                }
            });

            Thread printThread = new Thread(() -> {
                for (int i = 0; i < vector.size(); i++) {
                    System.out.println(vector.get(i));
                }
            });

            removeThread.start();
            printThread.start();
            //不要同时产生过程的线程，否则会导致操作系统假死
            while (Thread.activeCount() > 20);
        }
    }
}
